#pragma once

#include <map>
#include <mutex>
#include <string>
#include <vector>

#include "BondInfo.h"
#include "bondlib.h"
typedef struct STR_BOND_HOLIDAY {
  char country[8];
  char market[8];
  //	int		holiday;
  char status[4];
  char flag;
  char HolidayReason[32];
} BondHoliday;

class S_BONDLIB_EXPORT BondHolidayList {
 public:
  std::vector<BondHoliday> holidays;
};

class S_BONDLIB_EXPORT CBondHoliday {
 public:
  std::map<int, BondHolidayList> date;  // 主键=日期
};

class S_BONDLIB_EXPORT CBondCalendar {
 public:
  struct BondHolidays_ {
    int nNaturalDays;
    int nWorkingDays;
    BondHolidays_() {
      nNaturalDays = 0;
      nWorkingDays = 0;
    }
  };

 public:
  static CBondCalendar &instance();
  void Clear();
  void Add(int nDate, BondHoliday &element);

  int GetSize();
  bool GetHolidayByDate(const std::string &szCountry,
                        const std::string &szMarket, int nDate);
  bool GetBondHolidayById(const std::string &szMarket, int nDate,
                          BondHoliday &stHoliday);
  CBondHoliday &GetBondHoliday();

  void CalcHolidays(const std::string sMarket, time_t tBegin, time_t tEnd,
                    BondHolidays_ &bhd_);
  //-------------------------------------------------------------------------
  // Summary:
  // 		判断债券是否满足中国的节假日
  // Parameters:
  // 		bondInfo - 债券
  //      nRemainerDays - 剩余天数据
  //      dLimitRemainYears - 剩余期限限制，默认为1年
  // Returns:
  // 		满足节假日返回true，否则返回false
  //-------------------------------------------------------------------------
  // bool IsHoliday_CHY(const CBondInfo& bondInfo,double dLimitRemainYears
  // = 1.0); bool IsHoliday_CHY(const CBondInfo& bondInfo, int &nRemaindays,
  // double dLimitRemainYears = 1.0){ return false; };
  bool IsHoliday_CHY(const CBondInfo &bondInfo, bool &isCIB, int &nDayCIB,
                     int &nDaySSE);
  bool IsHoliday_CHY_Time(const CBondInfo &bondInfo, const time_t tNow,
                          bool &isCIB, int &nDayCIB, int &nDaySSE);

  //-------------------------------------------------------------------------
  // Summary:
  // 		判断某天是否会节假日
  // Parameters:
  // 		szCountry - 国家
  // 		szMarket - 市场
  // 		nDate - 天数
  // Returns:
  // 		若是节假日成功返回true,否则返回false
  //-------------------------------------------------------------------------
  bool IsHoliday(const std::string &szCountry, const std::string &szMarket,
                 int nDate);
  bool IsHoliday(const std::string &szCountry, const std::string &szMarket,
                 time_t tTime);

  //-------------------------------------------------------------------------
  // Summary:
  // 		nDate增加一天，nDate格式为20150901
  // Parameters:
  // 		nDate - 日期
  // Returns:
  // 		nDate日期增加一天
  //-------------------------------------------------------------------------
  static int IncreaseOneDay(int &nDate);
  static int ReduceOneDay(int &nDate);  // 减一天
  static int IncreaseDay(int &nDate, int nDays);
  static time_t IntToTime(int nDate);
  static int TimeToInt(time_t tTime);

  //-------------------------------------------------------------------------
  // Summary:
  // 		计算天数差值
  // Parameters:
  // 		nStartDate -  开始日 格式为20150901
  // 		nEndDate -    结束日 格式为20150901
  // Returns:
  // 		天数
  //-------------------------------------------------------------------------
  static int DiffDays(int nStartDate, int nEndDate);

  //-------------------------------------------------------------------------
  // Summary:
  // 		判断债券是否满足中国的节假日，一级系统
  // Parameters:
  // 		bondInfo - 债券
  //      nRemainerDays - 剩余天数据
  // Returns:
  // 		满足节假日返回true，否则返回false
  //-------------------------------------------------------------------------
  // bool IsHoliday_CHY_Primary(const CBondInfo& bondInfo);
  // bool IsHoliday_CHY_Primary(const CBondInfo& bondInfo, int &nRemaindays){
  // return false; };
  bool IsHoliday_CHY_Primary(const CBondInfo &bondInfo, const time_t tNow,
                             bool &isCIB, int &nDayCIB, int &nDaySSE);

  std::mutex &GetMutex() { return m_mutex; }

 public:
  // 工具函数
  static void GetNextTradingDay(time_t &t, const char *cCountry,
                                const char *cMarket, bool bWeekend);
  static void GetNextTradingDay(time_t &t, bool bWeekend = false);

  static void GetPreTradingDay(time_t &tm, const char *cCountry,
                               const char *cMarket, bool bWeekend /*= false*/);
  static void GetPreTradingDay(time_t &tm, bool bWeekend /*= false*/);

 public:
  void DumpStatus(int mode = 0) const;

 private:
  CBondCalendar();
  virtual ~CBondCalendar();

 protected:
  CBondHoliday m_holiday;
  std::mutex m_mutex;
};
